﻿using INTEX.DataBase;
using INTEX.DataBase.Tools;
using ReflectionStudio.Core;
using ReflectionStudio.Core.Events;
using ReflectionStudio.Core.Reflection;
using ReflectionStudio.LocalizationLibrary;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Configuration;
using System.Data;
using System.Data.OracleClient;
using System.Data.SqlClient;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.ServiceModel;
using WPFExcelReport.Helpers;
namespace WPFExcelReport
{
    public class ApplicationBase
    {
        public ApplicationBase()
        {
            myHashtable = CheckExcellProcesses();
            KillExcel(myHashtable);
        }
        public void Quit()
        {
            try
            {
                Dictionary<string, object> a = new Dictionary<string, object>();
                a.Add("QAGENT", proxyInstance.AgentID);
                proxy.RequestAgentStart(a);
                if (proxy != null)
                {
                    proxy.Close();
                }
            }
            catch (Exception ex)
            { }
        }
        ~ApplicationBase()
        {
          
        }
        public log4net.ILog m_log_out = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        ExcelX.ExcelLib.ExcelAgent exAgent;
        INTEXDBC INTEXDBC;
        public SETINTEXDB SetUser = new SETINTEXDB();
        public string Updater
        {
            get
            {
                return (string)EnvExe["Updater"];
            }

        }
        public DataTable UserTable
        {
            get
            {
                return SetUser.ICC_MENUDEF;
            }
        }
        public string company
        {
            get
            {
                return (string)EnvExe["Company"];
            }
        }
        string CHECKFOLDER = "NO";
        public string SqlDB
        {
            get
            {
                return (string)EnvExe["SqlDB"];
            }
        }
        public string ROOTDRIVE
        {
            get
            {
                return (string)EnvExe["ROOTDRIVE"];
            }
        }
        public string SubFolders
        {
            get
            {
                return (string)EnvExe["SubFolders"];
            }
        }
        public string DocType
        {
            get
            {
                return (string)EnvExe["DocType"];
            }
        }
        public string User
        {
            get
            {
                return (string)EnvExe["User"];
            }
        }
        public bool BYAGENT
        {
            get
            {
                if (EnvExe.ContainsKey("BYAGENT"))
                {
                    if ((string)EnvExe["BYAGENT"] == "NO")
                        return false;
                }
                return true;
            }
        }

        public string Pwd
        {
            get
            {
                return (string)EnvExe["Pwd"];
            }
        }
        public string Mandant
        {
            get
            {
                return (string)EnvExe["MANDANT"];
            }
        }
        Hashtable myHashtable;

        private Dictionary<string, object> EnvExe;
        public OracleConnection OracleDB;
        public string ApplicationPath
        {
            get { return System.IO.Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath); }
        }
        public string lib
        {
            get { return System.IO.Directory.GetParent(ApplicationPath) + "\\Lib"; }
        }
        public string LayoutFile
        {
            get { return System.IO.Path.Combine(ApplicationPath, "IntexReportClient.Layout.xml"); }
        }
        public Dictionary<string, object> dicParamater
        {
            get
            {
                return EnvExe;
            }
        }
        public void GetID()
        {
            proxy.BYAGENT = BYAGENT;
            DataSet SResult = proxyInstance.RequestAgentStart(new Dictionary<string, object>());
            if (SResult.Tables.Count == 0)
                return;
            foreach (DataRow row in SResult.Tables[0].Rows)
            {
                proxyInstance.AgentID = row["AGENTID"].ToString();
            }
        }
        public void Load()
        {
            proxyInstance = new IntexReptServBLClient();
           
            EnvExe = new Dictionary<string, object>();
            ReadConfig(ref EnvExe);
            if (EnvExe.ContainsKey("CHECKFOLDER"))
            {
                CHECKFOLDER = (string)EnvExe["CHECKFOLDER"];
            }
            EnvExe.Add("m_log_out", m_log_out);
            EnvExe.Add("proxy", proxy);
            EnvExe.Add("blBuildCellMastrix", false);
            EnvExe.Add("_Control", this);
            EnvExe.Add("dsParamaters", null);
            EnvExe.Add("ExCelNameMatrix", null);
            EnvExe.Add("USERRIGHT", null);
            EnvExe.Add("OracleDB", null);
            EnvExe.Add("SqlServerDB", null);
            EnvExe["ExcelFile"] = Path.Combine(PathHelper.ApplicationPath, @"Report\" + company + "\\" + EnvExe["ExcelFile"].ToString().Trim());
            GetID();
            Connect2DB();
            INTEXDBC = new INTEXDBC(OracleDB, proxy);
            SetUser.Merge(LoadSetSETUP(company, User));
        }
        //proxy = new IntexReptServBLClient();
        private IntexReptServBLClient proxyInstance;
        public IntexReptServBLClient proxy
        {
            get
            {
                if (proxyInstance == null)
                {
                    AttemptToConnect();
                }
                return this.proxyInstance;
            }
        }

        private void ProxyChannelFaulted(object sender, EventArgs e)
        {
            bool connected = false;
            while (!connected)
            {
                // you may want to put timer code around this, or 
                // other code to limit the number of retrys if 
                // the connection keeps failing
                AttemptToConnect();
            }
        }

        public bool AttemptToConnect()
        {
            // this whole process needs to be thread safe
            lock (proxyInstance)
            {
                try
                {
                    if (proxyInstance != null)
                    {
                        // deregister the event handler from the old instance
                        proxyInstance.InnerChannel.Faulted -= new EventHandler(ProxyChannelFaulted);
                    }

                    //(re)create the instance
                    proxyInstance = new IntexReptServBLClient();
                    // always open the connection
                    proxyInstance.Open();

                    // add the event handler for the new instance
                    // the client faulted is needed to be inserted here (after the open)
                    // because we don't want the service instance to keep faulting (throwing faulted event)
                    // as soon as the open function call.
                    proxyInstance.InnerChannel.Faulted += new EventHandler(ProxyChannelFaulted);

                    return true;
                }
                catch (EndpointNotFoundException ex)
                {
                    Tracer.Error(ex.StackTrace, ex);
                    return false;
                }
                catch (TimeoutException ex)
                {
                    Tracer.Error(ex.StackTrace, ex);
                    // do something here (log, show user message etc.)
                    return false;
                }
            }
        }


        private void Connect2DB()
        {
            string strIntexSystem = (string)EnvExe["dbSystem"];
            string strUserName = (string)EnvExe["dbUser"];
            string strPassWord = (string)EnvExe["dbPwd"];

            string OracleDBConnString = "user id=" + strUserName
                    + ";data source=" + strIntexSystem
                    + ";password=" + strPassWord + ";Unicode=True;"
                       + "Persist Security Info=True;";
            if (OracleDB != null)
            {
                OracleDB.Close();
            }
            OracleDB = new OracleConnection(OracleDBConnString);
            OracleDB.ConnectionString = OracleDBConnString;
            EnvExe["OracleDB"] = OracleDB;
            EnvExe["OracleDBConnString"] = OracleDBConnString;
            SqlConnection SqlServerDB = new SqlConnection(EnvExe["SqlDB"].ToString());
            EnvExe["SqlServerDB"] = SqlServerDB;
            EnvExe["SqlServerDBConnString"] = EnvExe["SqlDB"].ToString();
        }
        private void ReadConfig(ref Dictionary<string, object> env)
        {
            string key = "";
            string value = "";
            NameValueCollection appSettings = ConfigurationManager.AppSettings;
            for (int i = 0; i < appSettings.Count; i++)
            {
                key = appSettings.GetKey(i);
                value = appSettings[i];
                if (env.ContainsKey(key))
                {
                    env[key] = value;
                }
                else
                {
                    env.Add(key, value);
                }
            }
        }
        public Hashtable CheckExcellProcesses()
        {
            Process[] AllProcesses = Process.GetProcessesByName("EXCEL");
            Hashtable myHashtable = new Hashtable();
            int iCount = 0;

            foreach (Process ExcelProcess in AllProcesses)
            {
                myHashtable.Add(ExcelProcess.Id, iCount);
                iCount = iCount + 1;
            }
            return myHashtable;
        }
        public void KillExcel(Hashtable myHashtable)
        {
            Process[] AllProcesses = Process.GetProcessesByName("EXCEL");

            // check to kill the right process
            foreach (Process ExcelProcess in AllProcesses)
            {
                if (myHashtable.ContainsKey(ExcelProcess.Id) == false)
                    ExcelProcess.Kill();
            }

            AllProcesses = null;
        }

        public DataSet ReSetSETUP()
        {
            DataSet setReturn = new DataSet();
            DataSet setResult = new DataSet();
            DataSet settemp = new DataSet();
            /*
            ArrayList tables = new ArrayList();
            string fileroot = ApplicationPath + @"\Documents";
            string filePath = "";

            string[] files = System.IO.Directory.GetFiles(fileroot);
            //string filepath = Path.Combine(PathHelper.ApplicationPath, @"Report\Interface\CADMAPINTEX.xls");
            string ShortName = "";

            foreach (string file in files)
            {
                if (!file.EndsWith("SETUP.xls"))
                    continue;
                if (exAgent == null)
                {
                    exAgent = new ExcelX.ExcelLib.ExcelAgent(file);
                }
                setResult = exAgent.LoadDataTableDef(file, "");

                foreach (DataTable tbTemp in setResult.Tables)
                {
                    string tbName = tbTemp.TableName;
                    settemp = new DataSet();
                    settemp.DataSetName = "SETUP";
                    settemp.Merge(tbTemp);
                    filePath = fileroot + "\\" + tbName + ".XML";
                    if (System.IO.File.Exists(filePath))
                    {
                        System.IO.File.Delete(filePath);
                    }
                    settemp.WriteXml(filePath);
                }
            }
            exAgent.Close();*/
            DataSet SResult = LoadSetSETUP(company, User);
            SetUser.Merge(SResult);
            return setReturn;
        }

        public DataSet LoadSetSETUP(string company, string user)
        {
            DataSet setReturn = new DataSet();
            DataSet setResult = new DataSet();
            DataRow dwData = null;
            dwData = SetUser.ICC_MENUDEF.NewRow();
            dwData["MANDANT"] = Mandant;
            dwData["COMPANY"] = company;
            dwData["USERID"] = Helper.Left(User + "    ", 8);
            setResult = INTEXDBC.QueryICC_MENUDEF(dwData, 2);
            setReturn.Merge(setResult);
            if (CHECKFOLDER == "YES")
            {
                dwData = SetUser.ICC_FOLDERS.NewRow();
                dwData["MANDANT"] = Mandant;
                setResult = INTEXDBC.QueryICC_FOLDERS(dwData, 9999);
                foreach (DataRow rowf in setResult.Tables[0].Rows)
                {
                    Helper.CheckDirectory(rowf["ROOT"].ToString(), rowf["SUB"].ToString());
                }
            }
            return setReturn;
        }
        public void LoadAssembly(ArrayList namelist)
        {
            foreach (var name in namelist)
            {
                LoadAssembly((string)name);
            }
        }
        public Assembly LoadAssembly(string name)
        {
            string root = lib;
            string path = "";
            Assembly result = null;
            Assembly assm = null;
            name = name.Trim();
            try
            {
                if (AssemblyManager.ReflectionCache.ProcessedAssemblies.ContainsKey(name))
                    return null;
                if (AssemblyManager.ReflectionCache.CurrentDomainAssemblies.ContainsKey(name))
                {
                    assm = AssemblyManager.ReflectionCache.CurrentDomainAssemblies[name].Assembly;
                }
                else
                {
                    path = Path.Combine(root, name + ".dll");
                    if (!File.Exists(path))
                    {
                        path = Path.Combine(root, name + ".exe");
                        if (!File.Exists(path))
                        {
                            return null;
                        }
                    }
                    assm = Assembly.LoadFrom(path);
                    AssemblyManager.ReflectionCache.AddToCurrentDomain(assm);
                    AssemblyName[] reflist = assm.GetReferencedAssemblies();
                    foreach (AssemblyName ass in reflist)
                    {
                        name = ass.Name;
                        LoadAssembly(name);
                    }
                }

            }
            catch (Exception ex)
            {
                Tracer.Error(ex.StackTrace, ex);
                Tracer.Info("LoadAssembly", name + " Failed");
            }  
            result = assm;
            return result;
        }
        public void LoadAssembly(Assembly assembly)
        {
            string name = "";

            name = assembly.GetName().Name;
            if (AssemblyManager.ReflectionCache.ProcessedAssemblies.ContainsKey(name))
                return;
            LocalizationManager.RegisterAssembly(assembly);
            //首先，对于已经加载到内存的dll，无需再次加载。 
            AssemblyManager.ReflectionCache.RefreshCurrentDomain();
        }
        public Type GetDoc(string doctype)
        {

            Assembly assembly;
            Type docType = null;
            EnvExe["DocType"] = doctype;
            string fullname = "";
            string file = "";

            if (SetUser.Tables.Contains(company + "USERRIGHT"))
            {
                EnvExe["USERRIGHT"] = SetUser.Tables[company + "USERRIGHT"];
            }
            if (doctype == "ITXSETUP")
            {
                file = "ITXSETUP.dll";
                fullname = "WPFExcelReport.ITXSETUP";
            }
            else
            {
                DataRow dwData = SetUser.ICC_FUNCTIONS.NewRow();
                dwData["MANDANT"] = "00";
                dwData["TYPE"] = Helper.Left(doctype + "                         ", 20);
                DataSet SResult = INTEXDBC.QueryICC_FUNCTIONS(dwData, 2);
                if (SResult.Tables.Count == 0)
                    return docType;
                foreach (DataRow dwFile in SResult.Tables[0].Rows)
                {
                    file = dwFile["FILENAME"].ToString().Trim();
                    fullname = dwFile["NAMESPACE"].ToString().Trim() + "." + dwFile["FULLNAME"].ToString().Trim();
                }
            }
            assembly = LoadAssembly(file.Replace(".dll", ""));
            if (assembly == null)
                return docType;
            docType = assembly.GetType(fullname);

            if (docType == null)
                return docType;
            if (doctype == "ARTICLE")
                EnvExe["blBuildCellMastrix"] = true;

            return docType;
        }

    }
}
